package com.panopset.gui;

import static com.panopset.Util.log;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import com.panopset.Strings;
import com.panopset.Util;
import com.panopset.UtilIO;
import com.panopset.centralen.resource.Favicon;
import com.panopset.swing.App;
import com.panopset.swing.Document;
import com.panopset.swing.FieldGui;
import com.panopset.swing.Scaffolding;
import java.util.ArrayList;

/**
 *
 * Edit property values.
 *
 * @author Karl Dinwiddie
 * @deprecated
 *
 */
public abstract class PropvalEditor extends Document {

    public PropvalEditor(final String propertiesFileName) {
        this(null, propertiesFileName);
        if (true) {
            throw new RuntimeException();
        }
    }

    /**
     * @param defaultResourcePath
     *            Default resource path.
     * @param propertiesFileName
     *            Name of properties file, relative to the application base
     *            directory.
     */
    public PropvalEditor(final String defaultResourcePath,
            final String propertiesFileName) {
        super(defaultResourcePath, propertiesFileName);
        setFieldGui(new FieldGui() {

            @Override
            public String getValue() {
                StringWriter sw = new StringWriter();
                for (Entry<PVEID, ValidatingDataEntry> entry : getOrderedEntries()
                        .entrySet()) {
                    sw.append(entry.getKey().toString());
                    sw.append(UtilIO.MAP_SEP);
                    try {
						sw.append(entry.getValue().getValue());
					} catch (Exception e) {
						Util.log(e);
					}
                    sw.append(Strings.getEol());
                }
                return sw.toString();
            }

            @Override
            public void setValue(final String value) {
                getPropsPanel().removeAll();

                RowConstraints dlc = new RowConstraints(2);

                StringReader sr = new StringReader(value);
                BufferedReader br = new BufferedReader(sr);
                if (keysplr != null) {
                    for (PVEID nv : keysplr.getKeys()) {
                        getDataEntry(nv);
                    }
                }
                try {
                    String s = br.readLine();
                    while (s != null) {
                        StringTokenizer st = new StringTokenizer(s,
                                UtilIO.MAP_SEP);
                        String key = "";
                        String val = "";
                        if (st.hasMoreElements()) {
                            key = st.nextToken();
                        }
                        if (st.hasMoreElements()) {
                            val = st.nextToken();
                        }
                        getDataEntry(new PVEID(key)).setValue(val);
                        s = br.readLine();
                    }
                } catch (IOException ex) {
                    log(ex);
                }
                for (Entry<PVEID, ValidatingDataEntry> e : getOrderedEntries()
                        .entrySet()) {
                    ValidatingDataEntry de = e.getValue();
                    GridBagConstraints[] gbc = dlc.getNextRowConstraints();
                    getPropsPanel().add(
                            new JLabel("   " + e.getKey().getLabel()), gbc[0]);
                    getPropsPanel().add(de.getTitledPanel().getPanel(), gbc[1]);
                    de.updateGui();
                }
                getPropsPanel().invalidate();
                UtilGUI.updateComponent(getPropsPanel());
            }
        });
        if (true) {
            throw new RuntimeException();
        }
    }

    /**
     * Number of test keys is 2.
     */
    private static final int NUM_KEYS = 2;
    /**
     * 100.
     */
    private static final int ABOUT_SIZE = 100;

    /**
     * Test PropvalEditor.
     *
     * @param s
     *            Not used.
     */
    public static void main(final String... s) throws Exception {
        Scaffolding.s.setHome(new File(UtilIO.combinePaths(UtilIO.getHome(),
                "Panopset")));
        new App(new Favicon(Favicon.PANOPSET_ICON_PATH)) {
            @Override
            public String getApplicationName() {
                return "PropvalEditorTest";
            }

            @Override
            public Component createMainPanel() {
                PropvalEditor pve = new PropvalEditorInteger(null, "foo.txt");
                pve.setKeySupplier(new KeySupplier() {

                    @Override
                    public List<PVEID> getKeys() {
                        List<PVEID> s = new ArrayList<PVEID>();
                        for (int i = 0; i < NUM_KEYS; i++) {
                            StringBuilder lbl = new StringBuilder();
                            lbl.append("y" + i);
                            s.add(new PVEID(lbl.toString(), "k" + i));
                        }
                        return s;
                    }
                });
                return pve.getPanel();
            }

            @Override
            protected PopupBox getAboutBox() {
                return new PopupBox(new JPanel(), new Dimension(ABOUT_SIZE,
                        ABOUT_SIZE), App.app.f.getFrame()) {
                };
            }
        }.show();
    }

    public Map<PVEID, ValidatingDataEntry> getEntries() {
        getValue();
        return getOrderedEntries();
    }

    private Map<PVEID, ValidatingDataEntry> entries;

    private Map<PVEID, ValidatingDataEntry> getOrderedEntries() {
        if (entries == null) {
            entries = Collections
                    .synchronizedSortedMap(new TreeMap<PVEID, ValidatingDataEntry>());
        }
        return entries;
    }

    public void addKey(final String name) {
        PVEID key = new PVEID(name);
        getOrderedEntries().put(key, new ValidatingDataEntry(key));
    }

    /**
     * Get the data entry object for a given named key. It will be created if it
     * does not already exist.
     *
     * @param key
     *            Key.
     * @return Data entry.
     */
    private ValidatingDataEntry getDataEntry(final PVEID key) {
        ValidatingDataEntry de = getOrderedEntries().get(key);
        if (de == null) {
            de = new ValidatingDataEntry(key) {
                @Override
                public boolean validate(final String s) {
                    return PropvalEditor.this.validate(s);
                }
            };
            getOrderedEntries().put(key, de);
        }
        return de;
    }

    /**
     * Set key supplier.
     *
     * @param keySupplier
     *            Key supplier.
     */
    public void setKeySupplier(final KeySupplier keySupplier) {
        keysplr = keySupplier;
    }

    /**
     * @return Panel.
     */
    public TPanel getPanel() {
        if (panel == null) {
            panel = new TPanel();
            panel.setLayout(new BorderLayout());
            panel.add(BorderLayout.NORTH, new TLabel(getFileName()));
            panel.add(BorderLayout.CENTER, new JScrollPane(getPropsPanel()));
        }
        return panel;
    }

    /**
     * Key supplier.
     */
    private KeySupplier keysplr;
    /**
     * Props Panel.
     */
    private TPanel propsPanel;

    /**
     * @return Props panel.
     */
    private TPanel getPropsPanel() {
        if (propsPanel == null) {
            propsPanel = new TPanel(new GridBagLayout());
        }
        return propsPanel;
    }

    /**
     * Panel.
     */
    private TPanel panel;

    /**
     * @param s
     *            String to validate.
     * @return True iff valid.
     */
    protected abstract boolean validate(String s);
}
